package org.example.Page;

import org.example.POJO.game.Chess;
import org.example.POJO.game.ChessFactory;
import org.example.POJO.online.MyMessage;
import org.example.POJO.online.Record;
import org.example.Utils.SocketUtil;
import org.example.sever.ClientThread;

import javax.sound.sampled.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.LinkedList;


public class GamePanel extends JPanel {
    private Chess[] chesses = new Chess[32];

    private Chess selectedChess;//当前选择的棋子

    private int currentCamp = 1;//记住当前阵营 红为1 黑为0

    private JLabel hintLabel;

    private boolean isLocked = false;

    private String username;

    private String to;//对手名称

    private Socket socket;

    private MyFrame myFrame;

    private ClientThread ct;

    public ClientThread getCt() {
        return ct;
    }

    public void setMyFrame(MyFrame myFrame) {
        this.myFrame = myFrame;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    public void setTo(String to) {
        this.to = to;
    }

    //棋盘开关
    public void setLocked(boolean locked) {
        this.isLocked = locked;
    }

    private LinkedList<Record> history = new LinkedList<>();//每一步棋的历史记录


    public void setCurrentCamp(int currentCamp) {
        this.currentCamp = currentCamp;
    }

    //构造方法:保证先创建棋子再绘画
    public GamePanel() {
        createChesses();
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (isLocked) {
                    return;
                }
                //获取鼠标点击坐标
                Point point = Chess.getPointFromXY(e.getX(), e.getY());
                if (selectedChess == null) {
                    //第一次选择棋子
                    selectedChess = getChessByP(point);
                    //判断是否是当前阵营
                    if (selectedChess != null && selectedChess.getCamp() != currentCamp) {
                        selectedChess = null;
                        //可以用html编写
                        hintLabel.setText("请选择" + (currentCamp == 0 ? "黑方" : "红方"));
                    }
                    playSound("picture/audio/select.wav");
                } else {
                    Chess chess = getChessByP(point);
                    if (chess != null) {
                        //第n次选择
                        // 移动，吃子
                        if (chess.getCamp() == selectedChess.getCamp()) {
                            //重新选择
                            selectedChess = chess;
                            playSound("picture/audio/select.wav");
                        } else {
                            //吃子
                            if (selectedChess.isAbleMove(point, GamePanel.this)) {
                                playSound("picture/audio/eat.wav");
                                //移动记录
                                Record record = new Record();
                                record.setChess(selectedChess);
                                record.setStart(selectedChess.getPoint());
                                record.setEnd(point);
                                record.setEaten(chess);
                                history.add(record);
                                //从数组中删除被吃掉的棋子
                                chesses[chess.getIndex()] = null;
                                selectedChess.setPoint(point);
                                MyMessage request = new MyMessage();
                                request.setType(MyMessage.Type.EAT);
                                request.setFrom(username);
                                request.setTo(to);
                                request.setContent(record);
                                endTurn(record, request);
                            }
                        }
                    } else {
                        //第n次选择没有棋子，点击空白地方
                        //移动
                        if (selectedChess.isAbleMove(point, GamePanel.this)) {
                            playSound("picture/audio/go.wav");
                            //移动记录
                            Record record = new Record();
                            record.setChess(selectedChess);
                            record.setStart(selectedChess.getPoint());
                            record.setEnd(point);
                            record.setEaten(chess);
                            history.add(record);
                            selectedChess.setPoint(point);
                            MyMessage request = new MyMessage();
                            request.setType(MyMessage.Type.MOVE);
                            request.setFrom(username);
                            request.setTo(to);
                            request.setContent(record);
                            endTurn(record, request);
                        }

                    }
                }
                //刷新棋盘,重新执行paint方法，像动画
                repaint();
            }

        });
    }

    //悔棋
    public void back(MyMessage request) {
        Record record = history.pollLast();
        //恢复棋子的坐标
        record.getChess().setPoint(record.getStart());
        chesses[record.getChess().getIndex()] = record.getChess();
        if (record.getEaten() != null) {
            chesses[record.getEaten().getIndex()] = record.getEaten();
            playSound("picture/audio/seat.wav");
        }
        //还原阵营
        currentCamp = 1 - record.getChess().getCamp();

        if (request != null)
            //还原提示
            endTurn(record, request);
        //刷新棋盘
        repaint();
    }

    //结束当前回合
    public void endTurn(Record record, MyMessage request) {
        if (request != null)
            //发送消息给服务器,回合结束
            try {
                SocketUtil.send(socket, request);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        //锁定自己的棋盘
        isLocked = true;
        //修改提示信息
        selectedChess = null;
        hintLabel.setText("红方走".equals(hintLabel.getText()) ? "黑方走" : "红方走");

    }
    //音效
    private void playSound(String soundFilePath) {
        try {
            File soundFile = new File(soundFilePath);
            AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
            e.printStackTrace();
        }
    }


    public void setHintLabel(JLabel hintLabel) {
        this.hintLabel = hintLabel;
    }

    //根据网格坐标查找棋子
    public Chess getChessByP(Point p) {
        for (Chess chess : chesses) {
            if (chess != null && chess.getPoint().equals(p)) {
                return chess;
            }
        }
        return null;
    }

    //创建棋子
    private void createChesses() {
        String[] names = {"che", "ma", "xiang", "shi", "wang", "shi",
                "xiang", "ma", "che", "pao", "pao", "bing", "bing", "bing"
                , "bing", "bing"};
        int[] xs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 8, 1, 3, 5, 7, 9};
        for (int i = 0; i < names.length; i++) {

            Chess c = ChessFactory.create(names[i], 0, xs[i]);
            c.setIndex(i);
            chesses[i] = c;//将棋子保存到数组中
        }
        for (int i = 0; i < names.length; i++) {
            Chess c = ChessFactory.create(names[i], 1, xs[i]);
            c.reserve();
            c.setIndex(i + 16);
            chesses[c.getIndex()] = c;//将棋子保存到数组中
        }
    }

    //画棋子
    private void drawChesses(Graphics g) {
        for (Chess chess : chesses) {
            if (chess != null) {
                chess.draw(g, this);
            }
        }
    }

    //取棋子
    public Chess[] getChesses() {
        return chesses;
    }

    //设置棋子
    public void setChesses(Chess[] chesses) {
        this.chesses = chesses;
        repaint();
    }


    //画背景
    @Override
    public void paintComponent(Graphics g) {
        String backgroundPath = "picture/qizi/xqboard.gif";
        Image image = Toolkit.getDefaultToolkit().getImage(backgroundPath);
        g.drawImage(image, 0, 0, this);

        drawChesses(g);
        if (selectedChess != null) {
            selectedChess.drawBorder(g, this);
        }
    }

    //开启线程接受
    public void startReceive() {
        ct = new ClientThread(socket, new ClientThread.ResponseListener() {
            @Override
            public void Success(MyMessage response) {
                System.out.println("ClientThread::gamePanel::" + response);
                Object content = response.getContent();
                if (content instanceof Record) {
                    Record r = (Record) content;
                    switch (response.getType()) {
                        case CONNECT:
                            break;
                        case FIGHT:
                            break;
                        case MOVE:
                            chesses[r.getChess().getIndex()] = r.getChess();
                            history.add(r);
                            break;
                        case LIST:
                            break;
                        case EAT:
                            chesses[r.getEaten().getIndex()] = null;
                            chesses[r.getChess().getIndex()] = r.getChess();
                            history.add(r);
                            break;
                        case BACK:
                            System.out.println("GamePanel：：：悔棋");
                            back(null);
                            break;
                        case SUCCESS:
                            break;
                        case PEACE:
                            System.out.println("GamePanel：：：求和");
                            int result = JOptionPane.showConfirmDialog(null, "是否同意求和？", "对方发起的求和", JOptionPane.YES_NO_OPTION);
                            MyMessage request = new MyMessage();
                            request.setFrom(username);
                            request.setTo(to);
                            request.setContent(new Record());
                            if (result == JOptionPane.YES_OPTION) {
                                //同意
                                request.setType(MyMessage.Type.PEACE_SUCCESS);
                                ct.setShutdown(true);
                                myFrame.dispose();
                                try {
                                    new GameLobby(socket, username);
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                            } else {
                                //拒绝
                                request.setType(MyMessage.Type.PEACE_DEFEAT);
                            }
                            try {
                                SocketUtil.send(socket, request);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            break;
                        case PEACE_SUCCESS:
                            System.out.println("GamePanel：：：同意求和");
                            JOptionPane.showMessageDialog(null, "对战结束，平局");
                            ct.setShutdown(true);
                            myFrame.dispose();
                            try {
                                new GameLobby(socket, username);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            ct.setShutdown(true);
                            break;
                        case PEACE_DEFEAT:
                            System.out.println("GamePanel：：：拒绝求和");
                            JOptionPane.showMessageDialog(null, "对方拒绝求和");
                            if (("红方走".equals(hintLabel.getText()) && 1 == currentCamp) || ("黑方走".equals(hintLabel.getText()) && 0 == currentCamp)) {
                                isLocked = false;
                            }
                            break;
                        case DEFEAT:
                            JOptionPane.showMessageDialog(null, "对局结束对手认输了");
                            myFrame.dispose();
                            try {
                                new GameLobby(socket, username);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            ct.setShutdown(true);
                            break;
                        default:
                            break;
                    }
                    //解锁棋盘
                    isLocked = false;
                    //修改提示文字
                    hintLabel.setText("红方走".equals(hintLabel.getText()) ? "黑方走" : "红方走");
                    repaint();
                } else if (content instanceof String) {
                    switch (response.getType()) {
                        case CHAT:
                            myFrame.getChatDisplay().setText(response.getContent().toString());
                            break;
                        default:
                            break;
                    }
                }
            }
        });
        ct.start();
    }
}
